<?php


class Test
{
    public static function main()
    {
        // 创建机器人
        $robot = new EggRobot();
        // 机器人计算
        $robot->calculate();

        // 创建升级包visitor
        $updatePackVisitor = new UpdateVisitor();

        // 给机器人传升级包访问者
        $robot->accept($updatePackVisitor);

        $robot->calculate();
    }
}


class EggRobot
{
    protected $cpu;
    protected $hardDisk;

    public function __construct()
    {
        $this->cpu = new CPU('1+1=1');
        $this->hardDisk = new HardDisk('记住: 1+1=1');
    }

    public function calculate()
    {
        $this->cpu->run();
        $this->hardDisk->run();
    }

    /**
     * 分发升级包升级
     * @param Visitor $visitor
     */
    public function accept(Visitor $visitor)
    {
        // cpu把自己交给visitor改造
        $this->cpu->accept($visitor);
        // hardDisk把自己交给visitor改造
        $this->hardDisk->accept($visitor);
    }

}

interface Visitor
{
    public function visitCPU(CPU $cpu);

    public function visitHardDisk(HardDisk $hardDisk);
}

class UpdateVisitor implements Visitor
{

    public function visitCPU(CPU $cpu)
    {
        $cpu->command .= ': 1+1=2';
    }

    public function visitHardDisk(HardDisk $hardDisk)
    {
        $hardDisk->command .= "; 记住:1+1=2";
    }
}

/**
 * 硬件抽象类
 * Class Hardware
 */
abstract class Hardware
{
    /**
     * @var $command string
     */
    public $command;

    /**
     * @param string $command
     */
    public function __construct(string $command)
    {
        $this->command = $command;
    }

    public function run()
    {
        echo $this->command;
    }

    /**
     * 把自己交给visitor改造
     * @param Visitor $visitor
     * @return mixed
     */
    abstract function accept(Visitor $visitor);
}

class CPU extends Hardware
{
    function accept(Visitor $visitor)
    {
        $visitor->visitCPU($this);
    }
}

class HardDisk extends Hardware
{
    function accept(Visitor $visitor)
    {
        $visitor->visitHardDisk($this);
    }
}


Test::main();
